#ifndef __EVENT__H__
#define __EVENT__H__

#include "collaboration.h"

#define DEFAULT_EVENT_TYPE 0

/**
* @brief Clase que modela un evento generico
* @author Carlos Rodriguez Dominguez
*
* Esta clase se utilizara para modelar los diversos eventos
* que se usaran en el sistema. Cada evento debera tener una serie
* de campos creados mediante "create_member". Los listeners se
* encargaran de captar unos u otros eventos realizando los tests
* que consideren pertinentes mediante las funciones "exists_member",
* "member_value", "count_members", etc. Por defecto contiene un
* campo llamado "type" donde se guarda el tipo de evento especifico,
* que permitira tambien establecer filtros mediante listeners.
* Por defecto tiene un campo llamado "type" que contendra inicialmente
* el valor definido por DEFAULT_EVENT_TYPE. Este campo permitira diferenciar
* unos tipos de eventos de otros.
*/
class Event {
private:
	Collaboration::Event event; /**< Estructura que modela un evento */
	Ice::CommunicatorPtr comm;
	
public:	
	/**
	* Constructor por defecto. Crea un campo llamado "type",
	* cuyo valor inicial es el definido por DEFAULT_EVENT_TYPE.
	*/
	Event(const Ice::CommunicatorPtr& c);
	
	/**
	* Constructor a partir de la representacion interna de un evento.
	*
	* @param ev Representacion interna del evento.
	*/
	Event(const ::Collaboration::Event& ev, const Ice::CommunicatorPtr& c);
	
	/**
	* Destructor
	*/
	virtual ~Event();
	
	/**
	* Comprueba si un campo existe o no en el evento
	*
	* @param name Nombre del campo
	* @return True si el campo existe. False en caso contrario.
	*/
	bool existsMember(const ::std::string& name);
	
	/**
	* Obtiene el valor de un campo (si existe)
	*
	* @param name Nombre del campo
	* @param exists Booleano donde se indica si el campo existe o no
	* @return Tipo generico que modela el valor del campo especificado o
	*         valor nulo si el campo no existe
	*/
	Collaboration::EventData getMemberValue(const ::std::string& name, bool& exists);
	
	/**
	* Obtiene el valor de un campo (si existe)
	*
	* @param name Nombre del campo
	* @return Tipo generico que modela el valor del campo especificado o
	*         valor nulo si el campo no existe
	*/
	Collaboration::EventData getMemberValue(const ::std::string& name);
	
	/**
	* Asigna un valor a un campo (crea el campo si no existe)
	*
	* @param name Nombre del campo
	* @param value Valor para el campo
	*/
	void setMemberValue(const ::std::string& name, const Collaboration::EventData& value);
	
	/**
	* Cuenta el numero de campos del evento
	*
	* @return Numero de campos del evento
	*/
	unsigned int countMembers();
	
	/**
	* Obtiene el tipo concreto del evento
	*
	* @return Tipo del evento definido por el campo "type".
	*/
	int getType();
	
	/**
	* Obtiene la representacion interna del evento.
	*
	* @return Representacion interna del evento.
	*/
	Collaboration::Event internalEvent() const;
	
	/**
	* Metodos para interpretar bytes como tipos de datos (y viceversa).
	* Aceptan datos primitivos, vectores de estos datos u objetos proxy de ICE.
	*/
	
	bool interpretBool(const Collaboration::EventData& ev);
	::Ice::Byte interpretByte(const Collaboration::EventData& ev);
	short interpretShort(const Collaboration::EventData& ev);
	int interpretInt(const Collaboration::EventData& ev);
	long interpretLong(const Collaboration::EventData& ev); 
	float interpretFloat(const Collaboration::EventData& ev);
	double interpretDouble(const Collaboration::EventData& ev);
	::std::string interpretString(const Collaboration::EventData& ev);
	::Ice::ObjectPrx interpretObjectPrx(const Collaboration::EventData& ev);
	
	std::vector<bool> interpretBoolSeq(const Collaboration::EventData& ev);
	std::vector< ::Ice::Byte> interpretByteSeq(const Collaboration::EventData& ev);
	std::vector<short> interpretShortSeq(const Collaboration::EventData& ev);
	std::vector<int> interpretIntSeq(const Collaboration::EventData& ev);
	std::vector< ::Ice::Long> interpretLongSeq(const Collaboration::EventData& ev); 
	std::vector<float> interpretFloatSeq(const Collaboration::EventData& ev);
	std::vector<double> interpretDoubleSeq(const Collaboration::EventData& ev);
	std::vector< ::std::string> interpretStringSeq(const Collaboration::EventData& ev);
	
	Collaboration::EventData fromBool(bool b);
	Collaboration::EventData fromByte(::Ice::Byte b);
	Collaboration::EventData fromShort(short b);
	Collaboration::EventData fromInt(int b);
	Collaboration::EventData fromLong(long b);
	Collaboration::EventData fromFloat(float b);
	Collaboration::EventData fromDouble(double b);
	Collaboration::EventData fromString(const ::std::string& b);
	Collaboration::EventData fromObjectPrx(const ::Ice::ObjectPrx& b);
	
	Collaboration::EventData fromBoolSeq(const std::vector<bool>& b);
	Collaboration::EventData fromByteSeq(const std::vector< ::Ice::Byte>& b);
	Collaboration::EventData fromShortSeq(const std::vector<short>& b);
	Collaboration::EventData fromIntSeq(const std::vector<int>& b);
	Collaboration::EventData fromLongSeq(const std::vector< ::Ice::Long>& b);
	Collaboration::EventData fromFloatSeq(const std::vector<float>& b);
	Collaboration::EventData fromDoubleSeq(const std::vector<double>& b);
	Collaboration::EventData fromStringSeq(const std::vector< ::std::string>& b);
};

#endif
